home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / jpeglib5b / cjpeg.c < prev    next >
C/C++ Source or Header  |  1980-01-12  |  28KB  |  892 lines

  1. /*
  2.  * cjpeg.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  * To simplify script writing, the "-outfile" switch is provided.  The syntax
  22.  *    cjpeg [options]  -outfile outputfile  inputfile
  23.  * works regardless of which command line style is used.
  24.  */
  25.  
  26. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  27. #include "jversion.h"        /* for version message */
  28.  
  29. #include <ctype.h>        /* to declare isupper(), tolower() */
  30. #ifdef NEED_SIGNAL_CATCHER
  31. #include <signal.h>        /* to declare signal() */
  32. #endif
  33. #ifdef USE_SETMODE
  34. #include <fcntl.h>        /* to declare setmode()'s parameter macros */
  35. /* If you have setmode() but not <io.h>, just delete this line: */
  36. #include <io.h>            /* to declare setmode() */
  37. #endif
  38.  
  39. #ifdef USE_CCOMMAND        /* command-line reader for Macintosh */
  40. #ifdef __MWERKS__
  41. #include <SIOUX.h>              /* Metrowerks declares it here */
  42. #endif
  43. #ifdef THINK_C
  44. #include <console.h>        /* Think declares it here */
  45. #endif
  46. #endif
  47.  
  48. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  49. #define READ_BINARY    "r"
  50. #define WRITE_BINARY    "w"
  51. #else
  52. #define READ_BINARY    "rb"
  53. #define WRITE_BINARY    "wb"
  54. #endif
  55.  
  56. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  57. #define EXIT_FAILURE  1
  58. #endif
  59. #ifndef EXIT_SUCCESS
  60. #ifdef VMS
  61. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  62. #else
  63. #define EXIT_SUCCESS  0
  64. #endif
  65. #endif
  66. #ifndef EXIT_WARNING
  67. #ifdef VMS
  68. #define EXIT_WARNING  1        /* VMS is very nonstandard */
  69. #else
  70. #define EXIT_WARNING  2
  71. #endif
  72. #endif
  73.  
  74.  
  75. /* Create the add-on message string table. */
  76.  
  77. #define JMESSAGE(code,string)    string ,
  78.  
  79. static const char * const cdjpeg_message_table[] = {
  80. #include "cderror.h"
  81.   NULL
  82. };
  83.  
  84.  
  85. /*
  86.  * This routine determines what format the input file is,
  87.  * and selects the appropriate input-reading module.
  88.  *
  89.  * To determine which family of input formats the file belongs to,
  90.  * we may look only at the first byte of the file, since C does not
  91.  * guarantee that more than one character can be pushed back with ungetc.
  92.  * Looking at additional bytes would require one of these approaches:
  93.  *     1) assume we can fseek() the input file (fails for piped input);
  94.  *     2) assume we can push back more than one character (works in
  95.  *        some C implementations, but unportable);
  96.  *     3) provide our own buffering (breaks input readers that want to use
  97.  *        stdio directly, such as the RLE library);
  98.  * or  4) don't put back the data, and modify the input_init methods to assume
  99.  *        they start reading after the start of file (also breaks RLE library).
  100.  * #1 is attractive for MS-DOS but is untenable on Unix.
  101.  *
  102.  * The most portable solution for file types that can't be identified by their
  103.  * first byte is to make the user tell us what they are.  This is also the
  104.  * only approach for "raw" file types that contain only arbitrary values.
  105.  * We presently apply this method for Targa files.  Most of the time Targa
  106.  * files start with 0x00, so we recognize that case.  Potentially, however,
  107.  * a Targa file could start with any byte value (byte 0 is the length of the
  108.  * seldom-used ID field), so we provide a switch to force Targa input mode.
  109.  */
  110.  
  111. static boolean is_targa;    /* records user -targa switch */
  112.  
  113.  
  114. LOCAL cjpeg_source_ptr
  115. select_file_type (j_compress_ptr cinfo, FILE * infile)
  116. {
  117.   int c;
  118.  
  119.   if (is_targa) {
  120. #ifdef TARGA_SUPPORTED
  121.     return jinit_read_targa(cinfo);
  122. #else
  123.     ERREXIT(cinfo, JERR_TGA_NOTCOMP);
  124. #endif
  125.   }
  126.  
  127.   if ((c = getc(infile)) == EOF)
  128.     ERREXIT(cinfo, JERR_INPUT_EMPTY);
  129.   if (ungetc(c, infile) == EOF)
  130.     ERREXIT(cinfo, JERR_UNGETC_FAILED);
  131.  
  132.   switch (c) {
  133. #ifdef BMP_SUPPORTED
  134.   case 'B':
  135.     return jinit_read_bmp(cinfo);
  136. #endif
  137. #ifdef GIF_SUPPORTED
  138.   case 'G':
  139.     return jinit_read_gif(cinfo);
  140. #endif
  141. #ifdef PPM_SUPPORTED
  142.   case 'P':
  143.     return jinit_read_ppm(cinfo);
  144. #endif
  145. #ifdef RLE_SUPPORTED
  146.   case 'R':
  147.     return jinit_read_rle(cinfo);
  148. #endif
  149. #ifdef TARGA_SUPPORTED
  150.   case 0x00:
  151.     return jinit_read_targa(cinfo);
  152. #endif
  153.   default:
  154.     ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
  155.     break;
  156.   }
  157.  
  158.   return NULL;            /* suppress compiler warnings */
  159. }
  160.  
  161.  
  162. /*
  163.  * Signal catcher to ensure that temporary files are removed before aborting.
  164.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  165.  * we put "#define signal_catcher _abort" in jconfig.h.  Talk about bogus...
  166.  */
  167.  
  168. #ifdef NEED_SIGNAL_CATCHER
  169.  
  170. static j_common_ptr sig_cinfo;
  171.  
  172. GLOBAL void
  173. signal_catcher (int signum)
  174. {
  175.   if (sig_cinfo != NULL) {
  176.     if (sig_cinfo->err != NULL) /* turn off trace output */
  177.       sig_cinfo->err->trace_level = 0;
  178.     jpeg_destroy(sig_cinfo);    /* clean up memory allocation & temp files */
  179.   }
  180.   exit(EXIT_FAILURE);
  181. }
  182.  
  183. #endif
  184.  
  185.  
  186. /*
  187.  * Optional routine to display a percent-done figure on stderr.
  188.  */
  189.  
  190. #ifdef PROGRESS_REPORT
  191.  
  192. METHODDEF void
  193. progress_monitor (j_common_ptr cinfo)
  194. {
  195.   cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
  196.   int total_passes = prog->pub.total_passes + prog->total_extra_passes;
  197.   int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
  198.  
  199.   if (percent_done != prog->percent_done) {
  200.     prog->percent_done = percent_done;
  201.     if (total_passes > 1) {
  202.       fprintf(stderr, "\rPass %d/%d: %3d%% ",
  203.           prog->pub.completed_passes + prog->completed_extra_passes + 1,
  204.           total_passes, percent_done);
  205.     } else {
  206.       fprintf(stderr, "\r %3d%% ", percent_done);
  207.     }
  208.     fflush(stderr);
  209.   }
  210. }
  211.  
  212. #endif
  213.  
  214.  
  215. /*
  216.  * Argument-parsing code.
  217.  * The switch parser is designed to be useful with DOS-style command line
  218.  * syntax, ie, intermixed switches and file names, where only the switches
  219.  * to the left of a given file name affect processing of that file.
  220.  * The main program in this file doesn't actually use this capability...
  221.  */
  222.  
  223.  
  224. static const char * progname;    /* program name for error messages */
  225. static char * outfilename;    /* for -outfile switch */
  226.  
  227.  
  228. LOCAL void
  229. usage (void)
  230. /* complain about bad command line */
  231. {
  232.   fprintf(stderr, "usage: %s [switches] ", progname);
  233. #ifdef TWO_FILE_COMMANDLINE
  234.   fprintf(stderr, "inputfile outputfile\n");
  235. #else
  236.   fprintf(stderr, "[inputfile]\n");
  237. #endif
  238.  
  239.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  240.   fprintf(stderr, "  -quality N     Compression quality (0..100; 5-95 is useful range)\n");
  241.   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
  242. #ifdef ENTROPY_OPT_SUPPORTED
  243.   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
  244. #endif
  245. #ifdef TARGA_SUPPORTED
  246.   fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n");
  247. #endif
  248.   fprintf(stderr, "Switches for advanced users:\n");
  249. #ifdef DCT_ISLOW_SUPPORTED
  250.   fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
  251.       (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  252. #endif
  253. #ifdef DCT_IFAST_SUPPORTED
  254.   fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
  255.       (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  256. #endif
  257. #ifdef DCT_FLOAT_SUPPORTED
  258.   fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
  259.       (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  260. #endif
  261.   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
  262. #ifdef INPUT_SMOOTHING_SUPPORTED
  263.   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
  264. #endif
  265.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  266.   fprintf(stderr, "  -outfile name  Specify name for output file\n");
  267.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  268.   fprintf(stderr, "Switches for wizards:\n");
  269. #ifdef C_ARITH_CODING_SUPPORTED
  270.   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
  271. #endif
  272.   fprintf(stderr, "  -baseline      Force baseline output\n");
  273. #ifdef C_MULTISCAN_FILES_SUPPORTED
  274.   fprintf(stderr, "  -nointerleave  Create noninterleaved JPEG file\n");
  275. #endif
  276.   fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
  277.   fprintf(stderr, "  -qslots N[,...]    Set component quantization tables\n");
  278.   fprintf(stderr, "  -sample HxV[,...]  Set component sampling factors\n");
  279.   exit(EXIT_FAILURE);
  280. }
  281.  
  282.  
  283. LOCAL boolean
  284. keymatch (char * arg, const char * keyword, int minchars)
  285. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  286. /* keyword is the constant keyword (must be lower case already), */
  287. /* minchars is length of minimum legal abbreviation. */
  288. {
  289.   register int ca, ck;
  290.   register int nmatched = 0;
  291.  
  292.   while ((ca = *arg++) != '\0') {
  293.     if ((ck = *keyword++) == '\0')
  294.       return FALSE;        /* arg longer than keyword, no good */
  295.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  296.       ca = tolower(ca);
  297.     if (ca != ck)
  298.       return FALSE;        /* no good */
  299.     nmatched++;            /* count matched characters */
  300.   }
  301.   /* reached end of argument; fail if it's too short for unique abbrev */
  302.   if (nmatched < minchars)
  303.     return FALSE;
  304.   return TRUE;            /* A-OK */
  305. }
  306.  
  307.  
  308. LOCAL int
  309. qt_getc (FILE * file)
  310. /* Read next char, skipping over any comments (# to end of line) */
  311. /* A comment/newline sequence is returned as a newline */
  312. {
  313.   register int ch;
  314.   
  315.   ch = getc(file);
  316.   if (ch == '#') {
  317.     do {
  318.       ch = getc(file);
  319.     } while (ch != '\n' && ch != EOF);
  320.   }
  321.   return ch;
  322. }
  323.  
  324.  
  325. LOCAL long
  326. read_qt_integer (FILE * file)
  327. /* Read an unsigned decimal integer from a quantization-table file */
  328. /* Swallows one trailing character after the integer */
  329. {
  330.   register int ch;
  331.   register long val;
  332.   
  333.   /* Skip any leading whitespace, detect EOF */
  334.   do {
  335.     ch = qt_getc(file);
  336.     if (ch == EOF)
  337.       return EOF;
  338.   } while (isspace(ch));
  339.   
  340.   if (! isdigit(ch)) {
  341.     fprintf(stderr, "%s: bogus data in quantization file\n", progname);
  342.     exit(EXIT_FAILURE);
  343.   }
  344.  
  345.   val = ch - '0';
  346.   while (ch = qt_getc(file), isdigit(ch)) {
  347.     val *= 10;
  348.     val += ch - '0';
  349.   }
  350.   return val;
  351. }
  352.  
  353.  
  354. LOCAL void
  355. read_quant_tables (j_compress_ptr cinfo, char * filename, int scale_factor,
  356.            boolean force_baseline)
  357. /* Read a set of quantization tables from the specified file.
  358.  * The file is plain ASCII text: decimal numbers with whitespace between.
  359.  * Comments preceded by '#' may be included in the file.
  360.  * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
  361.  * The tables are implicitly numbered 0,1,etc.
  362.  * NOTE: does not affect the qslots mapping, which will default to selecting
  363.  * table 0 for luminance (or primary) components, 1 for chrominance components.
  364.  * You must use -qslots if you want a different component->table mapping.
  365.  */
  366. {
  367.   /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
  368.   /* read in natural order (left to right, top to bottom). */
  369.   static const int ZIG[DCTSIZE2] = {
  370.      0,  1,  5,  6, 14, 15, 27, 28,
  371.      2,  4,  7, 13, 16, 26, 29, 42,
  372.      3,  8, 12, 17, 25, 30, 41, 43,
  373.      9, 11, 18, 24, 31, 40, 44, 53,
  374.     10, 19, 23, 32, 39, 45, 52, 54,
  375.     20, 22, 33, 38, 46, 51, 55, 60,
  376.     21, 34, 37, 47, 50, 56, 59, 61,
  377.     35, 36, 48, 49, 57, 58, 62, 63
  378.     };
  379.   FILE * fp;
  380.   int tblno, i;
  381.   long val;
  382.   unsigned int table[DCTSIZE2];
  383.  
  384.   if ((fp = fopen(filename, "r")) == NULL) {
  385.     fprintf(stderr, "%s: can't open %s\n", progname, filename);
  386.     exit(EXIT_FAILURE);
  387.   }
  388.   tblno = 0;
  389.  
  390.   while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
  391.     if (tblno >= NUM_QUANT_TBLS) {
  392.       fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
  393.       exit(EXIT_FAILURE);
  394.     }
  395.     table[0] = (unsigned int) val;
  396.     for (i = 1; i < DCTSIZE2; i++) {
  397.       if ((val = read_qt_integer(fp)) == EOF) {
  398.     fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
  399.     exit(EXIT_FAILURE);
  400.       }
  401.       table[ZIG[i]] = (unsigned int) val;
  402.     }
  403.     jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
  404.     tblno++;
  405.   }
  406.  
  407.   fclose(fp);
  408. }
  409.  
  410.  
  411. LOCAL void
  412. set_quant_slots (j_compress_ptr cinfo, char *arg)
  413. /* Process a quantization-table-selectors parameter string, of the form
  414.  *     N[,N,...]
  415.  * If there are more components than parameters, the last value is replicated.
  416.  */
  417. {
  418.   int val = 0;            /* default table # */
  419.   int ci;
  420.   char ch;
  421.  
  422.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  423.     if (*arg) {
  424.       ch = ',';            /* if not set by sscanf, will be ',' */
  425.       if (sscanf(arg, "%d%c", &val, &ch) < 1)
  426.     usage();
  427.       if (ch != ',')
  428.     usage();        /* syntax check */
  429.       if (val < 0 || val >= NUM_QUANT_TBLS) {
  430.     fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
  431.         NUM_QUANT_TBLS-1);
  432.     exit(EXIT_FAILURE);
  433.       }
  434.       cinfo->comp_info[ci].quant_tbl_no = val;
  435.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  436.     ;
  437.     } else {
  438.       /* reached end of parameter, set remaining components to last table */
  439.       cinfo->comp_info[ci].quant_tbl_no = val;
  440.     }
  441.   }
  442. }
  443.  
  444.  
  445. LOCAL void
  446. set_sample_factors (j_compress_ptr cinfo, char *arg)
  447. /* Process a sample-factors parameter string, of the form
  448.  *     HxV[,HxV,...]
  449.  * If there are more components than parameters, "1x1" is assumed.
  450.  */
  451. {
  452.   int ci, val1, val2;
  453.   char ch1, ch2;
  454.  
  455.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  456.     if (*arg) {
  457.       ch2 = ',';        /* if not set by sscanf, will be ',' */
  458.       if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
  459.     usage();
  460.       if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
  461.     usage();        /* syntax check */
  462.       if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
  463.     fprintf(stderr, "JPEG sampling factors must be 1..4\n");
  464.     exit(EXIT_FAILURE);
  465.       }
  466.       cinfo->comp_info[ci].h_samp_factor = val1;
  467.       cinfo->comp_info[ci].v_samp_factor = val2;
  468.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  469.     ;
  470.     } else {
  471.       /* reached end of parameter, set remaining components to 1x1 sampling */
  472.       cinfo->comp_info[ci].h_samp_factor = 1;
  473.       cinfo->comp_info[ci].v_samp_factor = 1;
  474.     }
  475.   }
  476. }
  477.  
  478.  
  479. LOCAL int
  480. parse_switches (j_compress_ptr cinfo, int argc, char **argv,
  481.         int last_file_arg_seen, boolean for_real)
  482. /* Parse optional switches.
  483.  * Returns argv[] index of first file-name argument (== argc if none).
  484.  * Any file names with indexes <= last_file_arg_seen are ignored;
  485.  * they have presumably been processed in a previous iteration.
  486.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  487.  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  488.  * processing.
  489.  */
  490. {
  491.   int argn;
  492.   char * arg;
  493.   int quality;            /* -quality parameter */
  494.   int q_scale_factor;        /* scaling percentage for -qtables */
  495.   boolean force_baseline;
  496.   char * qtablefile = NULL;    /* saves -qtables filename if any */
  497.   char * qslotsarg = NULL;    /* saves -qslots parm if any */
  498.   char * samplearg = NULL;    /* saves -sample parm if any */
  499.  
  500.   /* Set up default JPEG parameters. */
  501.   /* Note that default -quality level need not, and does not,
  502.    * match the default scaling for an explicit -qtables argument.
  503.    */
  504.   quality = 75;            /* default -quality value */
  505.   q_scale_factor = 100;        /* default to no scaling for -qtables */
  506.   force_baseline = FALSE;    /* by default, allow 16-bit quantizers */
  507.   is_targa = FALSE;
  508.   outfilename = NULL;
  509.   cinfo->err->trace_level = 0;
  510.  
  511.   /* Scan command line options, adjust parameters */
  512.  
  513.   for (argn = 1; argn < argc; argn++) {
  514.     arg = argv[argn];
  515.     if (*arg != '-') {
  516.       /* Not a switch, must be a file name argument */
  517.       if (argn <= last_file_arg_seen) {
  518.     outfilename = NULL;    /* -outfile applies to just one input file */
  519.     continue;        /* ignore this name if previously processed */
  520.       }
  521.       break;            /* else done parsing switches */
  522.     }
  523.     arg++;            /* advance past switch marker character */
  524.  
  525.     if (keymatch(arg, "arithmetic", 1)) {
  526.       /* Use arithmetic coding. */
  527. #ifdef C_ARITH_CODING_SUPPORTED
  528.       cinfo->arith_code = TRUE;
  529. #else
  530.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  531.           progname);
  532.       exit(EXIT_FAILURE);
  533. #endif
  534.  
  535.     } else if (keymatch(arg, "baseline", 1)) {
  536.       /* Force baseline output (8-bit quantizer values). */
  537.       force_baseline = TRUE;
  538.  
  539.     } else if (keymatch(arg, "dct", 2)) {
  540.       /* Select DCT algorithm. */
  541.       if (++argn >= argc)    /* advance to next argument */
  542.     usage();
  543.       if (keymatch(argv[argn], "int", 1)) {
  544.     cinfo->dct_method = JDCT_ISLOW;
  545.       } else if (keymatch(argv[argn], "fast", 2)) {
  546.     cinfo->dct_method = JDCT_IFAST;
  547.       } else if (keymatch(argv[argn], "float", 2)) {
  548.     cinfo->dct_method = JDCT_FLOAT;
  549.       } else
  550.     usage();
  551.  
  552.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  553.       /* Enable debug printouts. */
  554.       /* On first -d, print version identification */
  555.       static boolean printed_version = FALSE;
  556.  
  557.       if (! printed_version) {
  558.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  559.         JVERSION, JCOPYRIGHT);
  560.     printed_version = TRUE;
  561.       }
  562.       cinfo->err->trace_level++;
  563.  
  564.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  565.       /* Force a monochrome JPEG file to be generated. */
  566.       jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
  567.  
  568.     } else if (keymatch(arg, "maxmemory", 3)) {
  569.       /* Maximum memory in Kb (or Mb with 'm'). */
  570.       long lval;
  571.       char ch = 'x';
  572.  
  573.       if (++argn >= argc)    /* advance to next argument */
  574.     usage();
  575.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  576.     usage();
  577.       if (ch == 'm' || ch == 'M')
  578.     lval *= 1000L;
  579.       cinfo->mem->max_memory_to_use = lval * 1000L;
  580.  
  581.     } else if (keymatch(arg, "nointerleave", 3)) {
  582.       /* Create noninterleaved file. */
  583. #ifdef C_MULTISCAN_FILES_SUPPORTED
  584.       cinfo->interleave = FALSE;
  585. #else
  586.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  587.           progname);
  588.       exit(EXIT_FAILURE);
  589. #endif
  590.  
  591.     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  592.       /* Enable entropy parm optimization. */
  593. #ifdef ENTROPY_OPT_SUPPORTED
  594.       cinfo->optimize_coding = TRUE;
  595. #else
  596.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  597.           progname);
  598.       exit(EXIT_FAILURE);
  599. #endif
  600.  
  601.     } else if (keymatch(arg, "outfile", 4)) {
  602.       /* Set output file name. */
  603.       if (++argn >= argc)    /* advance to next argument */
  604.     usage();
  605.       outfilename = argv[argn];    /* save it away for later use */
  606.  
  607.     } else if (keymatch(arg, "quality", 1)) {
  608.       /* Quality factor (quantization table scaling factor). */
  609.       if (++argn >= argc)    /* advance to next argument */
  610.     usage();
  611.       if (sscanf(argv[argn], "%d", &quality) != 1)
  612.     usage();
  613.       /* Change scale factor in case -qtables is present. */
  614.       q_scale_factor = jpeg_quality_scaling(quality);
  615.  
  616.     } else if (keymatch(arg, "qslots", 2)) {
  617.       /* Quantization table slot numbers. */
  618.       if (++argn >= argc)    /* advance to next argument */
  619.     usage();
  620.       qslotsarg = argv[argn];
  621.       /* Must delay setting qslots until after we have processed any
  622.        * colorspace-determining switches, since jpeg_set_colorspace sets
  623.        * default quant table numbers.
  624.        */
  625.  
  626.     } else if (keymatch(arg, "qtables", 2)) {
  627.       /* Quantization tables fetched from file. */
  628.       if (++argn >= argc)    /* advance to next argument */
  629.     usage();
  630.       qtablefile = argv[argn];
  631.       /* We postpone actually reading the file in case -quality comes later. */
  632.  
  633.     } else if (keymatch(arg, "restart", 1)) {
  634.       /* Restart interval in MCU rows (or in MCUs with 'b'). */
  635.       long lval;
  636.       char ch = 'x';
  637.  
  638.       if (++argn >= argc)    /* advance to next argument */
  639.     usage();
  640.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  641.     usage();
  642.       if (lval < 0 || lval > 65535L)
  643.     usage();
  644.       if (ch == 'b' || ch == 'B') {
  645.     cinfo->restart_interval = (unsigned int) lval;
  646.     cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
  647.       } else {
  648.     cinfo->restart_in_rows = (int) lval;
  649.     /* restart_interval will be computed during startup */
  650.       }
  651.  
  652.     } else if (keymatch(arg, "sample", 2)) {
  653.       /* Set sampling factors. */
  654.       if (++argn >= argc)    /* advance to next argument */
  655.     usage();
  656.       samplearg = argv[argn];
  657.       /* Must delay setting sample factors until after we have processed any
  658.        * colorspace-determining switches, since jpeg_set_colorspace sets
  659.        * default sampling factors.
  660.        */
  661.  
  662.     } else if (keymatch(arg, "smooth", 2)) {
  663.       /* Set input smoothing factor. */
  664.       int val;
  665.  
  666.       if (++argn >= argc)    /* advance to next argument */
  667.     usage();
  668.       if (sscanf(argv[argn], "%d", &val) != 1)
  669.     usage();
  670.       if (val < 0 || val > 100)
  671.     usage();
  672.       cinfo->smoothing_factor = val;
  673.  
  674.     } else if (keymatch(arg, "targa", 1)) {
  675.       /* Input file is Targa format. */
  676.       is_targa = TRUE;
  677.  
  678.     } else {
  679.       usage();            /* bogus switch */
  680.     }
  681.   }
  682.  
  683.   /* Post-switch-scanning cleanup */
  684.  
  685.   if (for_real) {
  686.  
  687.     /* Set quantization tables for selected quality. */
  688.     /* Some or all may be overridden if -qtables is present. */
  689.     jpeg_set_quality(cinfo, quality, force_baseline);
  690.  
  691.     if (qtablefile != NULL)    /* process -qtables if it was present */
  692.       read_quant_tables(cinfo, qtablefile, q_scale_factor, force_baseline);
  693.  
  694.     if (qslotsarg != NULL)    /* process -qslots if it was present */
  695.       set_quant_slots(cinfo, qslotsarg);
  696.  
  697.     if (samplearg != NULL)    /* process -sample if it was present */
  698.       set_sample_factors(cinfo, samplearg);
  699.  
  700.   }
  701.  
  702.   return argn;            /* return index of next arg (file name) */
  703. }
  704.  
  705.  
  706. /*
  707.  * The main program.
  708.  */
  709.  
  710. GLOBAL int
  711. main (int argc, char **argv)
  712. {
  713.   struct jpeg_compress_struct cinfo;
  714.   struct jpeg_error_mgr jerr;
  715. #ifdef PROGRESS_REPORT
  716.   struct cdjpeg_progress_mgr progress;
  717. #endif
  718.   int file_index;
  719.   cjpeg_source_ptr src_mgr;
  720.   FILE * input_file;
  721.   FILE * output_file;
  722.   JDIMENSION num_scanlines;
  723.  
  724.   /* On Mac, fetch a command line. */
  725. #ifdef USE_CCOMMAND
  726.   argc = ccommand(&argv);
  727. #endif
  728.  
  729.   progname = argv[0];
  730.   if (progname == NULL || progname[0] == 0)
  731.     progname = "cjpeg";        /* in case C library doesn't provide it */
  732.  
  733.   /* Initialize the JPEG compression object with default error handling. */
  734.   cinfo.err = jpeg_std_error(&jerr);
  735.   jpeg_create_compress(&cinfo);
  736.   /* Add some application-specific error messages (from cderror.h) */
  737.   jerr.addon_message_table = cdjpeg_message_table;
  738.   jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  739.   jerr.last_addon_message = JMSG_LASTADDONCODE;
  740.  
  741.   /* Now safe to enable signal catcher. */
  742. #ifdef NEED_SIGNAL_CATCHER
  743.   sig_cinfo = (j_common_ptr) &cinfo;
  744.   signal(SIGINT, signal_catcher);
  745. #ifdef SIGTERM            /* not all systems have SIGTERM */
  746.   signal(SIGTERM, signal_catcher);
  747. #endif
  748. #endif
  749.  
  750.   /* Initialize JPEG parameters.
  751.    * Much of this may be overridden later.
  752.    * In particular, we don't yet know the input file's color space,
  753.    * but we need to provide some value for jpeg_set_defaults() to work.
  754.    */
  755.  
  756.   cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
  757.   jpeg_set_defaults(&cinfo);
  758.  
  759.   /* Scan command line to find file names.
  760.    * It is convenient to use just one switch-parsing routine, but the switch
  761.    * values read here are ignored; we will rescan the switches after opening
  762.    * the input file.
  763.    */
  764.  
  765.   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  766.  
  767. #ifdef TWO_FILE_COMMANDLINE
  768.   /* Must have either -outfile switch or explicit output file name */
  769.   if (outfilename == NULL) {
  770.     if (file_index != argc-2) {
  771.       fprintf(stderr, "%s: must name one input and one output file\n",
  772.           progname);
  773.       usage();
  774.     }
  775.     outfilename = argv[file_index+1];
  776.   } else {
  777.     if (file_index != argc-1) {
  778.       fprintf(stderr, "%s: must name one input and one output file\n",
  779.           progname);
  780.       usage();
  781.     }
  782.   }
  783. #else
  784.   /* Unix style: expect zero or one file name */
  785.   if (file_index < argc-1) {
  786.     fprintf(stderr, "%s: only one input file\n", progname);
  787.     usage();
  788.   }
  789. #endif /* TWO_FILE_COMMANDLINE */
  790.  
  791.   /* Open the input file. */
  792.   if (file_index < argc) {
  793.     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  794.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  795.       exit(EXIT_FAILURE);
  796.     }
  797.   } else {
  798.     /* default input file is stdin */
  799. #ifdef USE_SETMODE        /* need to hack file mode? */
  800.     setmode(fileno(stdin), O_BINARY);
  801. #endif
  802. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  803.     if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
  804.       fprintf(stderr, "%s: can't open stdin\n", progname);
  805.       exit(EXIT_FAILURE);
  806.     }
  807. #else
  808.     input_file = stdin;
  809. #endif
  810.   }
  811.  
  812.   /* Open the output file. */
  813.   if (outfilename != NULL) {
  814.     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  815.       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  816.       exit(EXIT_FAILURE);
  817.     }
  818.   } else {
  819.     /* default output file is stdout */
  820. #ifdef USE_SETMODE        /* need to hack file mode? */
  821.     setmode(fileno(stdout), O_BINARY);
  822. #endif
  823. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  824.     if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
  825.       fprintf(stderr, "%s: can't open stdout\n", progname);
  826.       exit(EXIT_FAILURE);
  827.     }
  828. #else
  829.     output_file = stdout;
  830. #endif
  831.   }
  832.  
  833. #ifdef PROGRESS_REPORT
  834.   /* Enable progress display, unless trace output is on */
  835.   if (jerr.trace_level == 0) {
  836.     progress.pub.progress_monitor = progress_monitor;
  837.     progress.completed_extra_passes = 0;
  838.     progress.total_extra_passes = 0;
  839.     progress.percent_done = -1;
  840.     cinfo.progress = &progress.pub;
  841.   }
  842. #endif
  843.  
  844.   /* Figure out the input file format, and set up to read it. */
  845.   src_mgr = select_file_type(&cinfo, input_file);
  846.   src_mgr->input_file = input_file;
  847.  
  848.   /* Read the input file header to obtain file size & colorspace. */
  849.   (*src_mgr->start_input) (&cinfo, src_mgr);
  850.  
  851.   /* Now that we know input colorspace, fix colorspace-dependent defaults */
  852.   jpeg_default_colorspace(&cinfo);
  853.  
  854.   /* Adjust default compression parameters by re-parsing the options */
  855.   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  856.  
  857.   /* Specify data destination for compression */
  858.   jpeg_stdio_dest(&cinfo, output_file);
  859.  
  860.   /* Start compressor */
  861.   jpeg_start_compress(&cinfo, TRUE);
  862.  
  863.   /* Process data */
  864.   while (cinfo.next_scanline < cinfo.image_height) {
  865.     num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
  866.     (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
  867.   }
  868.  
  869.   /* Finish compression and release memory */
  870.   (*src_mgr->finish_input) (&cinfo, src_mgr);
  871.   jpeg_finish_compress(&cinfo);
  872.   jpeg_destroy_compress(&cinfo);
  873.  
  874.   /* Close files, if we opened them */
  875.   if (input_file != stdin)
  876.     fclose(input_file);
  877.   if (output_file != stdout)
  878.     fclose(output_file);
  879.  
  880. #ifdef PROGRESS_REPORT
  881.   /* Clear away progress display */
  882.   if (jerr.trace_level == 0) {
  883.     fprintf(stderr, "\r                \r");
  884.     fflush(stderr);
  885.   }
  886. #endif
  887.  
  888.   /* All done. */
  889.   exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  890.   return 0;            /* suppress no-return-value warnings */
  891. }
  892.